package cn.com.cetccst.compliancecheck.checker;

import static cn.com.cetccst.datacenter.policy.entity.ComplianceBase.ACTION_WARN;

import android.content.Context;
import android.text.TextUtils;
import android.text.format.DateUtils;

import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.work.BackoffPolicy;
import androidx.work.Data;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;

import com.google.gson.Gson;

import org.json.JSONException;
import org.json.JSONObject;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import cn.com.cetccst.compliancecheck.kv.KVKeys;
import cn.com.cetccst.compliancecheck.worker.CheckComplianceWorker;
import cn.com.cetccst.datacenter.policy.PolicyRepository;
import cn.com.cetccst.datacenter.policy.entity.ComplianceEntity;
import cn.com.cetccst.datacenter.policy.entity.PolicyEntity;
import cn.com.cetccst.datacenter.policy.type.Compliance;
import cn.com.cetccst.tools.kv.CommonKV;
import cn.com.cetccst.tools.log.CommonLogger;

public class CheckerManager {


    private Compliance compliance;
    private final List<Checker> checkerList;
    private static CheckerManager instance;
    private final LiveData<PolicyEntity> complianceEntify;
    private int intervalHours;
    private int effectiveHours;
    private final WorkManager workManager;
    private final PeriodicWorkRequest periodicWork;
    public CheckerManager(Context context) {
        checkerList = new ArrayList<>();

        workManager = WorkManager.getInstance(context);
        periodicWork = new PeriodicWorkRequest.Builder(
                CheckComplianceWorker.class,
                Duration.ofMinutes(15))
                .setBackoffCriteria(
                        BackoffPolicy.LINEAR,
                        Duration.ofMinutes(5))
//                .setInitialDelay(1_000, TimeUnit.MILLISECONDS)
                .build();

        complianceEntify = PolicyRepository.getInstance().getPolicy(PolicyEntity.POLICY_COMPLIANCE);
        //动态监听合规性策略的变化，从而驱动UI和事件的执行
        complianceEntify.observeForever(policyEntity -> {
            CommonLogger.info("load compliance data from DB");
            initCompliance(context, policyEntity);
        });
    }

    public static void initialize(Context context) {
        if (instance == null) {
            DeviceModelChecker.init(context);
            OSVersionChecker.init(context);
            ApplicationChecker.init(context);
            RootChecker.init(context);
            SIMCardChecker.init(context);
            LocationChecker.init(context);
            SystemTimeChecker.init(context);
            ConnectionChecker.init(context);
            InstallSourceChecker.init(context);

            instance = new CheckerManager(context);
        }

    }

    public static CheckerManager getInstance() {
        return instance;
    }

    public void reset() {
        checkerList.clear();
    }

    public List<Checker> getCheckerList() {
        return checkerList;
    }

    public void setInterval(int intervalHours) {
        this.intervalHours = intervalHours;
    }

    public void setEffective(int effectiveHours) {
        this.effectiveHours = effectiveHours;
    }

    public int getIntervalHours() {
        return intervalHours;
    }

    public int getEffectiveHours() {
        return effectiveHours;
    }

    public void checkAll(Context context) {
        for (Checker checker : checkerList) {
            checker.check(context);
        }
        //保存到数据库
        saveAllCheckers();
    }

    public void saveAllCheckers() {
        List<ComplianceEntity> entities = new ArrayList<>();
        for (Checker checker : checkerList) {
            //有一些后续更新的checker，当结果发生变化后单独持久化到数据库
            ComplianceEntity entity = getComplianceEntity(checker);
            entities.add(entity);
        }

        PolicyRepository.getInstance().saveAllCompliance(entities);
    }

    @NonNull
    private ComplianceEntity getComplianceEntity(Checker checker) {
        ComplianceEntity entity = new ComplianceEntity();
        entity.setKey(checker.getType().getKey());
        entity.setStatus(checker.getResult().getStatus());
        entity.setPunish(checker.getAction());
        if (checker.getResult() == CheckResult.Violated
                && CommonKV.kvStore.decodeLong(KVKeys.KEY_COMPLIANCE + entity.getKey()) <= 0) {
            if (entity.getPunish() == ACTION_WARN) {
                CommonKV.kvStore.encode(KVKeys.KEY_COMPLIANCE + entity.getKey(), checker.getResult() == CheckResult.Pass ? -1 : System.currentTimeMillis());
            } else {
                CommonKV.kvStore.encode(KVKeys.KEY_COMPLIANCE + entity.getKey(), checker.getResult() == CheckResult.Pass ? -1 : System.currentTimeMillis() + effectiveHours * DateUtils.HOUR_IN_MILLIS);
            }
        }
        return entity;
    }

    /**
     * TODO 这里要不要判断数据库与内存是否一致，如果不一致再保存？
     *
     * @param checker
     */
    public void saveChecker(Checker checker) {
        ComplianceEntity entity = getComplianceEntity(checker);
        PolicyRepository.getInstance().saveCompliance(entity);
    }

    public void addChecker(Checker checker) {
        if (checker.isEnable()) {
            checkerList.add(checker);
        }
    }

    public String getCheckerName(String key) {
        for (Checker checker : checkerList) {
            if (checker.getType().getKey().equals(key)) {
                return checker.getName();
            }
        }
        return null;
    }


    private void initCompliance(Context context, PolicyEntity policyEntity) {
        CheckerManager.getInstance().reset();
        if (policyEntity != null && !TextUtils.isEmpty(policyEntity.getContent())) {

            String complianceBody = null;
            try {
                JSONObject complianceObj = new JSONObject(policyEntity.getContent());
                complianceBody = complianceObj.optString("compliance");
            } catch (JSONException e) {
                throw new RuntimeException(e);
            }
            compliance = new Gson().fromJson(complianceBody, Compliance.class);
            //黑白名单
            ApplicationChecker.getInstance().setAction(compliance.getBlackWhiteAppAction());
            CheckerManager.getInstance().addChecker(ApplicationChecker.getInstance());
            //连接性
            ConnectionChecker.getInstance().setAction(compliance.getConnectivityAction());
            ConnectionChecker.getInstance().setIntervalHours(compliance.getConnectivityIntervalHours());
            CheckerManager.getInstance().addChecker(ConnectionChecker.getInstance());
            //设备型号
            DeviceModelChecker.getInstance().setAction(compliance.getModelAction());
            DeviceModelChecker.getInstance().setModels(compliance.getModelValues());
            CheckerManager.getInstance().addChecker(DeviceModelChecker.getInstance());
            //地理围栏
            LocationChecker.getInstance().setAction(compliance.getDeviceGeoFence().getDeviceGeoFenceAction());
            LocationChecker.getInstance().setInnerOrOuter(compliance.getDeviceGeoFence().getGeoFenceInnerOrOuter());
            LocationChecker.getInstance().setGeoFence(compliance.getDeviceGeoFence().getValidLocation());
            CheckerManager.getInstance().addChecker(LocationChecker.getInstance());
            //系统版本
            OSVersionChecker.getInstance().setAction(compliance.getOsAction());
            OSVersionChecker.getInstance().setVersions(compliance.getOsVersions());
            CheckerManager.getInstance().addChecker(OSVersionChecker.getInstance());
            //Root
            RootChecker.getInstance().setAction(compliance.getRootAction());
            CheckerManager.getInstance().addChecker(RootChecker.getInstance());
            //SIM
            SIMCardChecker.getInstance().setAction(compliance.getDeviceBindingAction());
            CheckerManager.getInstance().addChecker(SIMCardChecker.getInstance());
            //Time
            SystemTimeChecker.getInstance().setAction(compliance.getTimeChangedAction());
            CheckerManager.getInstance().addChecker(SystemTimeChecker.getInstance());
            //Install source
            InstallSourceChecker.getInstance().setAction(compliance.getBlackWhiteAppAction());
            CheckerManager.getInstance().addChecker(InstallSourceChecker.getInstance());

            //时间设置
            CheckerManager.getInstance().setInterval(compliance.getIntervalHours());
            CheckerManager.getInstance().setEffective(compliance.getEffectiveHours());

//            workManager.cancelUniqueWork("CHECK_ALL_COMPLIANCE");
            workManager.enqueueUniquePeriodicWork(
                    "CHECK_ALL_COMPLIANCE",
                    ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
                    periodicWork);
        }
        else {
            workManager.cancelUniqueWork("CHECK_ALL_COMPLIANCE");
        }
    }

    public Compliance getCompliance() {
        return compliance;
    }
}
